package org.semanticflash.rdf.script
{
	
	
	import com.bigflexlib.core.markers.IValueSingleton;
	
	import flash.utils.Dictionary;
	
	import org.semanticflash.rdf.values.IRI;
	import org.semanticflash.rdf.values.RDFValue;
	
	
	/**
	 * 
	 * 
	 * @author aldo.bucchi@gmail.com
	 * 
	 */	
	public class RDFNodeFactory implements IValueSingleton
	{
		
		
		private var _provider:*;
		public function get provider( ):*
		{
			return _provider;
		}
	
	
	
	
		private var nodeCache:Dictionary = new Dictionary( true );
		
		
		private var typedNodeCache:Dictionary = new Dictionary( true );
	
	


		/**
		 * 
		 * @param provider
		 * 			we are not typing this until we have enough use cases to find a suitable generalization
		 * 
		 */
		public function RDFNodeFactory( provider:* )
		{
			
			_provider = provider;
			
		}
		
		


		public function getNode( value:RDFValue ):RDFNode
		{
		
			if ( ! nodeCache[ value ] )
			{
				var r:RDFNode = new RDFNode( this, value );
				
				nodeCache[ value ] = r;
				
				return r;
			}
			return nodeCache[ value ] as RDFNode;		
		}
		
		
		
		
		
		/**
		 * 
		 * 
		 * @param iri
		 * @param decoratorClass
		 * @return 
		 * 
		 */		
		public function getTypedNode( iri:IRI, decoratorClass:Class ):RDFTypedNode
		{
		
			if ( ! typedNodeCache[ iri ] ) // we use a 2D dictionary. First key is weak
			{
				typedNodeCache[ iri ] = new Dictionary( );
			}
			var cache:Dictionary = typedNodeCache[ iri ];
			
			
			if ( ! cache[ decoratorClass ] )			
			{
				var tr:RDFTypedNode = new decoratorClass( ) as RDFTypedNode;
				if ( tr == null )
				{
					return null; // TODO: throw error??
				}
				
				tr.initializeFromFactory( this, getNode( iri ) );
				
				cache[ decoratorClass ] = tr;
				return tr;
			}
			
			return cache[ decoratorClass ] as RDFTypedNode;
			
		
		}
		
		


		
		
		//////////////////////////////////////////////////
		// factory
		//////////////////////////////////////////////////
		
		private static var factoryCache:Dictionary = new Dictionary( true );
		
		public static function forProvider( provider:* ):RDFNodeFactory
		{
		
			if ( ! factoryCache[ provider ] )
			{
				var f:RDFNodeFactory = new RDFNodeFactory( provider );
				factoryCache[ provider ] = f;
				return f;
			}
			
			return factoryCache[ provider ] as RDFNodeFactory;
		
		}
		
		
		
		
		
		
		

		
	}
	

}